Mr.Peng 让你的App显示在“在…中打开…”菜单中
前言 朋友通过airDrop给我传图片时,接受后,自动保存在相册中了。但是当朋友通过airDrop给我发非图片非视频时,会提示”AirDrop打开方式…”,如下图:
那么如何让自己的app能够显示在菜单中?那么现在一步一来操作。
流程 从我自己的了解程度,总结以下流程,如果有问题,还待大家吐槽。
airdrop传输最初的接收者是ios系统本身,而非任何app;
当接收的文件是ios系统默认能够打开的(如.mp4、.jpeg、.tiff、iwork一套等是苹果默认能够打开的),在同意接收后,会自动保存在对应的目录下;
当接收的文件不是ios系统默认能够打开的,那么同意接受后,会弹出选择打开方式(即选择三方app)的菜单列表(下面称菜单);
三方app需要在系统中授权之后才能被加入到菜单;
以三方app打开之后,这时候app才算是接收者,就要在三方app中,用专用接口去把接收到的文件移动到本地app中文件目录下。
此时才能正常读取接受到的文件。
注:此过程没接收那么当然不会保存在系统中来,但是如果你一旦用三方app打开之后,系统中接收到的文件移动到三方app中,那么系统中文件被删除了,如果你接受了,没有选择三方app,那么系统会自动清除此文件。
理论 添加文档类型 要添加文档类型,请执行以下操作:
在您的Xcode项目中,选择要添加文档类型的目标。
选择信息选项卡。
单击文档类型的公开按钮以打开文档类型。
点击“+”按钮。
在新创建的文档类型中:
键入文档类型的名称。
在“类型”部分填写新类型的UTI。
提供文档的图标。
单击公开三角形以打开其他文档类型属性。
单击表中以添加新的键和值。
对于键值类型:CFBundleTypeRole。
对于值类型:编辑器。
单击+按钮添加另一个键/值对。
对于键值类型:LSHandlerRank。
对于值类型:Owner。
添加自定义UTI 如果要添加的文档类型是自定义文档类型或iOS不知道的文档类型,则需要为文档类型定义UTI。要添加新的UTI,请执行以下操作:
在您的Xcode项目中,选择要添加新UTI的目标。
选择信息选项卡。
单击导出的UTI的公开按钮。
点击“+”按钮。
选择“添加导出的UTI”。
在描述字段中,填写UTI的描述。
在标识符字段中,填写UTI的标识符。
在Conforms To字段中填写此新UTI符合的UTI列表。
切换“其他导出的UTI属性”公开三角形以打开一个表,您可以在其中添加一些其他信息。
单击空表,将显示可添加到表中的项目列表。
键入“UTTypeTagSpecification”。
将类型设置为字典。
单击显示三角形将其打开,然后单击表行中的+按钮添加条目。
对于“新项目”,将名称更改为“public.filename-extension”。
对于项目的类型,将其更改为“Array”。
切换打开刚刚添加的项,然后点击表格行中的+按钮。
对于项0,将“值”更改为文档的文件扩展名。例如,txt,pdf,docx等
实战 把app加入菜单中 创建新项目 此处省略XXX字
添加文档类型
增加类型
进入新项目的TARGETS
–Info
中Document Types
点击+
然后输入Name
和Types
,注意:Types
最好输入Bundle Identifier
。
增加Additional document type properties
点击 Additional document type properties
之前的倒三角,然后点击展开后的空白区域会出现key-value键值对,然后输入CFBundleTypeRole : Editor
和LSHandlerRank :Owner
两组键值对。
增加Exported UTIs
点击 Exported UTIs
之前的倒三角,填写Description
、Identifier
、Conforms To
信息
点击 Additional exported UTI properties
之前的倒三角,然后点击展开后的空白区域会出现key-value键值对,
1 2 3 4 5 6 7 8 9 10 { "UTTypeTagSpecification": { "public.filename-extension": [ { "item 0": "prdata", "url": "http://www.google.com" } ] } }
效果 通过airDrop发送.prdata
为后缀的文件,接收手机就能展示出来app名字了。
场景 除了上面的场景菜单中加入了三方app,还适合通过airDrop以三方app打开(如打开邮件中的附件)
读取文件信息 在appdelegate里面加入
1 - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options NS_AVAILABLE_IOS(9_0); // no equiv. notification. return NO if the application can't open for some reason
方法,处理系统传过来的URL,然后进行数据处理,代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options { if ([url isFileURL] && [[[url absoluteString] pathExtension] isEqualToString:@"prdata"]) { [self copyItemAtURLtoDocumentsDirectory:url]; return YES; } return NO; } //把接受到的文件移动到本地app文件目录下面 - (BOOL)copyItemAtURLtoDocumentsDirectory:(NSURL *)url { NSError *error; NSURL *copyToURL = [self applicationDocumentsDirectory]; NSString *fileName = [url lastPathComponent]; copyToURL = [copyToURL URLByAppendingPathComponent:fileName isDirectory:NO]; if ([[NSFileManager defaultManager] fileExistsAtPath:copyToURL.path]) { NSURL *duplicateURL = copyToURL; copyToURL = [copyToURL URLByDeletingPathExtension]; NSString *fileNameWithoutExtension = [copyToURL lastPathComponent]; //没有后缀的文件名 NSString *fileExtension = [url pathExtension]; //文件后缀 int i = 1; while ([[NSFileManager defaultManager] fileExistsAtPath:duplicateURL.path]) { //判断是否存在,存在就重新命名 copyToURL = [copyToURL URLByDeletingLastPathComponent]; copyToURL = [copyToURL URLByAppendingPathComponent:[NSString stringWithFormat:@"%@–%i", fileNameWithoutExtension, i]]; copyToURL = [copyToURL URLByAppendingPathExtension:fileExtension]; duplicateURL = copyToURL; i++; } } BOOL ok = [[NSFileManager defaultManager] moveItemAtURL:url toURL:copyToURL error:&error]; //把系统传过来的url对应的文件 移动到 本地app中 if (!ok) { NSLog(@"%@", [error localizedDescription]); } [[NSNotificationCenter defaultCenter] postNotificationName:@"kGetFileUrl" object:copyToURL.path]; return ok; } - (NSURL *)applicationDocumentsDirectory { NSString *documentsDirectory; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); if ([paths count] > 0) { documentsDirectory = [paths objectAtIndex:0]; } return [NSURL fileURLWithPath:documentsDirectory]; }
发送文件 在VC里面加入UIPopoverController
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 NSString *path1 = [[NSBundle mainBundle] pathForResource:@"blog" ofType:@"prdata"]; NSURL *url1 = [NSURL fileURLWithPath:path1]; PRAirDropData *item1 = [[PRAirDropData alloc] initWithURL:url1 subject:@"blog"]; NSArray *items = [NSArray arrayWithObjects:item1, nil]; UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:nil]; // Exclude all activities except AirDrop. NSArray *excludedActivities = @[UIActivityTypePostToTwitter, UIActivityTypePostToFacebook, UIActivityTypePostToWeibo, UIActivityTypeMessage, UIActivityTypeMail, UIActivityTypePrint, UIActivityTypeCopyToPasteboard, UIActivityTypeAssignToContact, UIActivityTypeSaveToCameraRoll, UIActivityTypeAddToReadingList, UIActivityTypePostToFlickr, UIActivityTypePostToVimeo, UIActivityTypePostToTencentWeibo]; activityViewController.excludedActivityTypes = excludedActivities; if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { [self presentViewController:activityViewController animated:YES completion:nil]; } else { if (![self.activityPopover isPopoverVisible]) { self.activityPopover = [[UIPopoverController alloc] initWithContentViewController:activityViewController]; [self.activityPopover presentPopoverFromRect:[sender1 frame] inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; } else { [self.activityPopover dismissPopoverAnimated:YES]; } }
源码 如果需要源码的请点击点击Demo
<
Mr.Peng解决xcode fetching list of team time out问题
Mr.Peng收集iOS三方资源库
>